import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as CANNON from 'cannon-es'
import { GUI } from 'lil-gui'

const gui = new GUI()

const world = new CANNON.World()
world.gravity.set(0, -0.98, 0) // 设置重力
// world.allowSleep = true

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight)
camera.position.set(0, 3, 5)
scene.add(camera)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.shadowMap.enabled = true
renderer.outputColorSpace = THREE.SRGBColorSpace

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

document.body.appendChild(renderer.domElement)

const axHelp = new THREE.AxesHelper(5)
scene.add(axHelp)

const light = new THREE.AmbientLight('#fff', 3)
scene.add(light)

const material = new CANNON.Material({ friction: 1 })

const sphereBody = new CANNON.Body({
  shape: new CANNON.Sphere(1), material, mass: 1, // mass 默认为0
  position: new CANNON.Vec3(-1, 1, 0),
})
world.addBody(sphereBody)

const sphere = new THREE.Mesh(
  new THREE.SphereGeometry(1, 10, 10),
  new THREE.MeshBasicMaterial({ color: 'red', wireframe: true })
)
scene.add(sphere)

const plane = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  new THREE.MeshBasicMaterial({ color: 'grey' })
)
plane.rotation.x = -Math.PI / 2
scene.add(plane)

const planeMaterial = new CANNON.Material('ground')
planeMaterial.friction = 0
planeMaterial.restitution = 1

const planeBody = new CANNON.Body({
  type: CANNON.Body.STATIC,
  material: planeMaterial,
}).addShape(new CANNON.Plane())
planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
world.addBody(planeBody)

sphereBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), Math.PI)

const debugParmas = {
  force() {
    // 第一个参数表示 李的大小 第二个参数表示位置
    sphereBody.applyForce(new CANNON.Vec3(10, 0, 0), new CANNON.Vec3(0, -1, 0))
  },
  localForce() {
    sphereBody.applyLocalForce(new CANNON.Vec3(10, 0, 0), new CANNON.Vec3(0, -1, 0))
  },
  scroll() {
    sphereBody.applyTorque(new CANNON.Vec3(0, 0, 10),)
  }
}

gui.add(debugParmas, 'force')
gui.add(debugParmas, 'localForce')
gui.add(debugParmas, 'scroll')

const clock = new THREE.Clock()
let preTime = 0

const handleRender = () => {
  const nowTime = clock.getElapsedTime()
  const deltaTime = nowTime - preTime
  preTime = nowTime

  world.step(1 / 60, deltaTime, 3) // 补帧操作
  sphere.position.copy(sphereBody.position as any)
  sphere.quaternion.copy(sphereBody.quaternion as any)

  controls.update()
  renderer.render(scene, camera)
  window.requestAnimationFrame(handleRender)
}

const handleSize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
}

window.addEventListener('resize', handleSize)

handleRender()
